#include "virtualfsobject.h"



VirtualFsObject::VirtualFsObject()
{
    _is_hidden = 0;
    _is_dir = false;
}


VirtualFsObject::VirtualFsObject(const QString & virtualWay, const QString & realWay,
                const QString & name, const QString & realName, bool __isdir)
{
    this->_virtualWay = virtualWay;
    this->_realWay = realWay;
    this->_name = name;
    _realName = realName;
    _is_dir = __isdir;
    _is_hidden = false;
}


VirtualFsObject::~VirtualFsObject()
{
    root.clear();
    clear_io();
}


int VirtualFsObject::size()
{
    int sz;
    
    mutex.lock();
      sz = root.size();
    mutex.unlock();
    
    return sz;
}


VirtualFsObject *VirtualFsObject::at(int i) {
    VirtualFsObject *v = 0;

    if(size() <= i) return v;
    mutex.lock();
      v = root[i];
    mutex.unlock();
    return v;
}


void VirtualFsObject::remove(int i)
{
    if(size() <= i) return;
    mutex.lock();
    root.remove(i);
    mutex.unlock();
}


void VirtualFsObject::clear()
{
    if(!size()) {
        return;
    }

    qWarning() << "Cleaning ..." << name() << "Real name: " << realName();

    if(!isDir()){
        return;
    }

    quint64 sz = size();
    for(quint64 i=0; i<sz; ++i)
    {
        VirtualFsObject *vfso = at(i);

        qWarning() << "for Cleaning ..." << vfso->name() << "Real name: " << vfso->realName();
        vfso->clear();

        remove(i);
        delete vfso;
        sz = size();
        i = -1;
    }

    mutex.lock();
      root.clear();
    mutex.unlock();
}


void VirtualFsObject::setVirtualWay(const QString & t)
{
    _virtualWay = t;
}


void VirtualFsObject::setRealWay(const QString & t)
{
    _realWay = t;
}


void VirtualFsObject::setName(const QString & t)
{
    _name = t;
}


void VirtualFsObject::setRealName(const QString & t)
{
    _realName = t;
}


void VirtualFsObject::setDirType(bool is)
{
    _is_dir = is;
}


VirtualFsObject *VirtualFsObject::push_back(VirtualFsObject *obj)
{
    root.push_back(obj);
    return this;
}



QFile *VirtualFsObject::getStreamById(int fd, bool lock)
{
    QFile *f;

    if(lock)
        io_mtx.lock();

    if(fd < 0 || fd >= __io_streams.size()) {
        if(lock) io_mtx.unlock();
        return 0;
    }

    f =__io_streams[fd];
    if(lock) io_mtx.unlock();
    return f;
}


void VirtualFsObject::clear_io()
{
    io_mtx.lock();
    QMap <int, QFile *>::iterator it = __io_streams.begin();
    for( ; it != __io_streams.end(); it++ )
    {
        fileClose(it.key(), false);
    }

    io_mtx.unlock();
}

void VirtualFsObject::bindStream(int fd, QFile *f, bool lock)
{
    if(getStreamById(fd, lock)) {
        qWarning() << "Critical error! stream " << fd << " exist in io base";
        return;
    }
    if(lock)
        io_mtx.lock();
    __io_streams[fd] = f;

    if(lock)
        io_mtx.unlock();
}


void VirtualFsObject::unbindStream(int fd, bool lock)
{
    if(!getStreamById(fd, lock)) {
        qWarning() << "Critical error! stream " << fd << " not exist in io base";
        return;
    }

    if(lock) io_mtx.lock();

    __io_streams.remove(fd);

    if(lock) io_mtx.unlock();
}


int VirtualFsObject::fileOpen()
{
    if(isDir())
        return -1;

    QFile *f = new QFile(realWay() + realName());
    f->open(QFile::ReadOnly);
    if(!f->isOpen())
    {
        delete f;
        return -1;
    }


    io_mtx.lock();
    int id = -1;
    for(int i = 0; ; ++i)
    {
        if(!getStreamById(i, false)) {
            id = i;
            break;
        }
    }

    bindStream(id, f, false);

    io_mtx.unlock();
    return id;
}


QByteArray VirtualFsObject::fileRead(int fd, quint64 sz)
{
    if(fd < 0) return _emprt_arr;
    QFile *f = getStreamById(fd, true);
    if(!f) return _emprt_arr;
    return f->read(sz);
}


int VirtualFsObject::fileClose(int fd, bool lock)
{
    QFile *f = getStreamById(fd, lock);
    if(!f) return -1;

    qWarning() << "IO: closing fd" << fd << " " << f->fileName();
    f->close();
    unbindStream(fd, lock);
    delete f;
    return 0;
}


bool VirtualFsObject::fileIsOpen(int fd)
{
    QFile *f = getStreamById(fd);
    if(!f) return false;

    return f->isOpen();
}


qint64 VirtualFsObject::fileSize(int fd)
{
    QFile *f = getStreamById(fd);
    if(!f) return 0;

    return f->size();
}


bool VirtualFsObject::fileSeek(int fd, qint64 pos)
{
    QFile *f = getStreamById(fd);
    if(!f) return -1;

    return f->seek(pos);
}


qint64 VirtualFsObject::fileTell(int fd)
{
    QFile *f = getStreamById(fd);
    if(!f) return 0;

    return f->pos();
}


